use strict;
use warnings;

package Plot;
use IPC::Run3 qw/run3/;
use TRFLP;

sub plot_raw_data {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 1, 0.5
#set yrange [-100:1000]
set yrange [1:]
set log y
set key left top
#plot "$file.sample" u 1 w histeps lt 0 ti "$key - sample", "$file.standard" u 1 w histeps lt -1 ti "$key - sizing ladder"
plot "$file.sample" u 1 w histeps lt 0 ti "$key - sample"
);
  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_target {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 2, 0.5
set origin 0,0
set multiplot
set origin 0,0.25
set size 2, 0.25
set key left top
set xtics("35"  35, "50" 50, "75" 75, "100" 100, "139" 139, "150" 150, "160" 160, "200" 200, "250" 250, "300" 300, "340" 340, "350" 350, "400" 400, "450" 450, "490" 490, "500" 500)
#set grid
plot "$file.target" u 1:2 w histeps lt -1 ti "target", "$file.target" u 1:3 w histeps lt 0 ti "$key - sizing ladder"
set origin 0,0
set size 2, 0.25
plot "$file.target" u 1:4 w histeps lt 14 ti "$key - sample"
);
  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_warped {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  # scale the time axis in basepairs
  my $line = `wc $file.warped`;
  my ( $npoints ) = ($line =~ /^\s*(\d+)/);
  $line = `tail -n 1 $file.warped`;
  my ( $xmax ) = ($line =~ /^\s*(\S+)/);
  my $scale = $xmax/$npoints;

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 10, 1
set origin 0, 0
set key left top
set lmargin 5
#set xrange [30:]
#set xtics("35"  35, "50" 50, "75" 75, "100" 100, "139" 139, "150" 150, "160" 160, "200" 200, "250" 250, "300" 300, "340" 340, "350" 350, "400" 400, "450" 450, "490" 490, "500" 500)
set xtics 5
set mxtics 5
set grid
set multiplot

set origin 0, 0.75
set size 10, 0.25
plot "$file.warped" u 1:2 w histeps lt 0 ti "target", "$file.warped" u 1:5 w histeps lt 3 ti "$key - warped ladder", "$file.warped" u 1:6 w histeps lt -1 ti "$key - ladder warped with interpolation"

set origin 0, 0.0
set size 10, 0.5
#plot "$file.warped" u 1:4 w histeps lt 14 ti "$key - sample", "$file.warped" u 1:7 w histeps lt 15 ti "$key - warped sample"
plot "$file.warped" u 1:7 w histeps lt 15 ti "$key - warped sample"

set origin 0, 0.5
set size 10, 0.25
set grid
set ytics 4
plot "$file.warped" u (\$1):($scale*\$8) w l lt 3 ti "$key - warping path (bp)", "$file.warped" u (\$1):($scale*\$9) w l lt -1 lw 3 ti "$key - interpolated warping path (bp)"
);
  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_clipped_ladder {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;


  my @x1;
  my @x2;
  open F1, "<$file" or die "can't open $file.standard: $!";
  open F2, "<$file.clipped" or die "can't open $file.standard.clippeded: $!";
  while ( my $x1 = <F1>, my $x2 = <F2> ) {
    push @x1, $x1;
    push @x2, $x2;
  }

  my $max = sprintf("%d", (sort {$a <=> $b} @x2)[-1]);
  push @input, qq(
set term png
set size 20, 0.5
set origin 0, 0
set yrange [-50:$max]
set xrange [1000:]
set key left top
plot "-" w lines lt 0 ti "$key: raw ladder", "-" w lines lt -1 ti "clipped ladder"
);
  push @input, @x1, "e\n";
  push @input, @x2, "e\n";

  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_peaks {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  $file =~ s/\.peak$//;

  my %oddpoint;
  my %evenpoint;
  open PEAK, "<$file.peak" or die "can't open $file.peak: $!";
  my $i = 0;
  while ( <PEAK> ) {
    chomp;
    my ($from, $to, @rest) = split "\t";
    if ( ++$i % 2 ) {
      foreach my $point ( $from .. $to ) {
	$evenpoint{$point}++;
      }
    }
    else {
      foreach my $point ( $from .. $to ) {
	$oddpoint{$point}++;
      }
    }
  }
  close PEAK;

  my @blank;
  my @odd;
  my @even;
  my @over;
  my @baseline;
  open SIGNAL, "<$file.deriv" or die "can't open $file.deriv: $!";
  $i = 1;
  while ( <SIGNAL> ) {
    chomp;
    s/^\s+//;
    my ($x, $baseline, $sig) = split /\s+/;
    push @baseline, "$x\t$baseline\n";
    my $value = ($oddpoint{$i} or $evenpoint{$i}) ? 0 : $sig;
    push @blank, "$x\t$value\n";
    $value = $oddpoint{$i} ? $sig : 0;
    push @odd, "$x\t$value\n";
    $value = $evenpoint{$i} ? $sig : 0;
    push @even, "$x\t$value\n";
    $value = ($evenpoint{$i} and $oddpoint{$i}) ? $sig : 0;
    push @over, "$x\t$value\n";
    $i++;
  }

  # scale the time axis in basepairs
  my $line = `wc $file.warped`;
  my ( $npoints ) = ($line =~ /^\s*(\d+)/);
  $line = `tail -n 1 $file.warped`;
  my ( $xmax ) = ($line =~ /^\s*(\S+)/);
  my $scale = $xmax/$npoints;

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 10, 1
set origin 0, 0
set key left top
set lmargin 8
#set xrange [30:]
set xtics 5
set mxtics 5
set grid
set multiplot

set origin 0, .75
set size 10, 0.25
plot "$file.warped" u 1:2 w histeps lt 0 ti "target", "$file.warped" u 1:5 w histeps lt 3 ti "$key - warped ladder", "$file.warped" u 1:6 w histeps lt -1 ti "$key - ladder warped with interpolation"

set origin 0, 0.0
set size 10, 0.5
set yrange [-100:2000]
#plot "$file.warped" u 1:7 w histeps lt 15 ti "$key - warped sample", "$file.deriv" u 1:2 w l lt 24 ti "$key - baseline", "$file.deriv" u 1:4 w l ti "D1", "$file.deriv" u 1:5 w l ti "D2"
plot "$file.warped" u 1:7 w histeps lt 15 ti "$key - warped sample", "$file.deriv" u 1:2 w l lt 24 ti "$key - baseline"

set origin 0, 0.5
set size 10, 0.25
set log y
set yrange[1:]
set xtics 5
set mxtics 5
set grid
plot '-' u 1:2 w histeps lt 0 ti "$key (noise)", '-' u 1:2 w boxes fs solid 1 lt 11 ti "peak", "-" u 1:2 w boxes fs solid 1 lt 31 ti "peak", '-' u 1:2 w boxes fs solid 1 lt 17 ti "overlap", '-' u 1:2 w boxes fs solid 1 lt 24 ti "baseline"
);
  push @input, @blank, "e\n";
  push @input, @odd, "e\n";
  push @input, @even, "e\n";
  push @input, @over, "e\n";
  push @input, @baseline, "e\n";

  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_logpeaks {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  $file =~ s/\.peak$//;

  my %oddpoint;
  my %evenpoint;
  open PEAK, "<$file.peak" or die "can't open $file.peak: $!";
  my $i = 0;
  while ( <PEAK> ) {
    chomp;
    my ($from, $to, @rest) = split "\t";
    if ( ++$i % 2 ) {
      foreach my $point ( $from .. $to ) {
	$evenpoint{$point}++;
      }
    }
    else {
      foreach my $point ( $from .. $to ) {
	$oddpoint{$point}++;
      }
    }
  }
  close PEAK;

  my @blank;
  my @odd;
  my @even;
  my @over;
  my @baseline;
  open SIGNAL, "<$file.deriv" or die "can't open $file.deriv: $!";
  $i = 1;
  while ( <SIGNAL> ) {
    chomp;
    s/^\s+//;
    my ($x, $baseline, $sig) = split /\s+/;
    push @baseline, "$x\t$baseline\n";
    my $value = ($oddpoint{$i} or $evenpoint{$i}) ? 0 : $sig;
    push @blank, "$x\t$value\n";
    $value = $oddpoint{$i} ? $sig : 0;
    push @odd, "$x\t$value\n";
    $value = $evenpoint{$i} ? $sig : 0;
    push @even, "$x\t$value\n";
    $value = ($evenpoint{$i} and $oddpoint{$i}) ? $sig : 0;
    push @over, "$x\t$value\n";
    $i++;
  }

  # scale the time axis in basepairs
  my $line = `wc $file.warped`;
  my ( $npoints ) = ($line =~ /^\s*(\d+)/);
  $line = `tail -n 1 $file.warped`;
  my ( $xmax ) = ($line =~ /^\s*(\S+)/);
  my $scale = $xmax/$npoints;

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 10, 0.5
set origin 0, 0
set key left top
set lmargin 8
#set xrange [30:]
set xtics 5
set mxtics 5
set grid
set multiplot

set origin 0, 0.25
set size 10, 0.25
plot "$file.warped" u 1:2 w histeps lt 0 ti "target", "$file.warped" u 1:5 w histeps lt 3 ti "$key - warped ladder", "$file.warped" u 1:6 w histeps lt -1 ti "$key - ladder warped with interpolation"

set origin 0, 0
set size 10, 0.25
set log y
set yrange[1:]
set xtics 5
set mxtics 5
set grid
plot '-' u 1:2 w histeps lt 0 ti "$key (noise)", '-' u 1:2 w boxes fs solid 1 lt 11 ti "peak", "-" u 1:2 w boxes fs solid 1 lt 31 ti "peak", '-' u 1:2 w boxes fs solid 1 lt 17 ti "overlap", '-' u 1:2 w boxes fs solid 1 lt 24 ti "baseline"
);
  push @input, @blank, "e\n";
  push @input, @odd, "e\n";
  push @input, @even, "e\n";
  push @input, @over, "e\n";
  push @input, @baseline, "e\n";

  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_heatmap {
  my %arg = @_;
  my $file = $arg{-file};
  my $key = $arg{-key};

  $file =~ s/\.peak$//;

  my @heatmap;
  open SIGNAL, "<$file.deriv" or die "can't open $file.deriv: $!";
  my $sigmax = 0;
  while ( <SIGNAL> ) {
    chomp;
    s/^\s+//;
    my ($x, $baseline, $sig) = split /\s+/;
    $sig =~ s/e.00//;
    $sig = 1 if $sig < 1;
    $sigmax = $sig if $sig > $sigmax;
    push @heatmap, "$x\t0\t$sig\n", "$x\t1\t$sig\n", "\n";
  }
#  $sigmax = $sigmax/2;
  $sigmax = 11 if $sigmax <= 10;
  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term postscript color
set size 0.08, 2
set origin 0, 0
set lmargin 0
set rmargin 0
set tmargin 0
set bmargin 0
set yrange [30:]
set zrange [0.1:1000]
set log z
unset xtics
unset ytics
set pm3d map
unset colorbox
splot '-' u 2:1:3
# Y X Z
);
  push @input, @heatmap, "e\n";

#  open DUMP, ">/tmp/gnuplot.dump";
#  print DUMP join("", @input);
#  close DUMP;
  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  @input = ($read_stdout);
  my @cmd = ('/usr/bin/convert', '-trim', '-flop', 'ps:-', 'png:-');
  run3 [@cmd], \@input, \$read_stdout, \$read_stderr
    or die "couldn't run3 this command: @cmd: $!\n";

  if ( $read_stderr ) {
    print STDERR "convert returned this error: $read_stderr\n@cmd\n";
  }

  return $read_stdout;
}

sub plot_cluster {
  my $file = "$TRFLP::tmpdir/ClusBinMatrix.txt";
  open CLUST, "<$file" or die "can't open $file: $!";
  my $row = 0;
  my @length;
  my @label;
  my %labelno;
  my @lines;
  while ( <CLUST> ) {
    chomp;
    my ($label, @data) = split "\t";
    $label =~ s/\"//g;
    $label = join("/", (split "/", $label)[-2,-1]) unless $label eq "length";
    if ( $row == 0 ) {
      @length = @data;
    }
    else {
      $label =~ s/\"//g;
      push @label, $label;
      $labelno{$label} = $row;
      foreach my $i ( 0 .. $#data ) {
	push @lines, "$row\t$length[$i]\t$data[$i]\n";
      }
      push @lines, "\n";
    }
    $row++;
  }

  my @input;
  my $read_stdout;
  my $read_stderr;

  my $graph_height = 0.1 * $row;

  push @input, qq(
set term postscript color eps 18
set lmargin 20
set size 3, $graph_height
set pm3d map
unset colorbox
unset xtics
set cbrange [0:0.1]
);
  push @input, "set ytics (" . join(", ", map {qq("$_" $labelno{$_})} @label) . ")\n";
  push @input, "splot '-' u 2:1:3 notitle\n";
  push @input, @lines, "e\n";

  open DUMP, ">/tmp/gnuplot.dump";
  print DUMP join("", @input);
  close DUMP;
  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  @input = ($read_stdout);
  run3 ['/usr/bin/convert', '-trim', 'ps:-', 'png:-'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "convert returned this error: $read_stderr";
  }

  return $read_stdout;
}

sub plot_overlayed {
  my %arg = @_;
  my @files = split ":", $arg{-files};
  my $signal = $arg{-signal};

  my $setlogy = "";
  my $setyrange = "";
  if ( $signal =~ /sample/ ) {
    $setlogy = "set log y";
    $setyrange = "set yrange [5:]";
  }

  # Put together the command to run gnuplot.
  my @input;
  my $read_stdout;
  my $read_stderr;

  push @input, qq(
set term png
set size 10, 0.5
set origin 0, 0
set key left top
set lmargin 8
set xrange [30:]
set xtics 5
set mxtics 5
set grid
$setlogy
$setyrange

plot );

  $input[-1] .= join ", ", map {qq( '-' u 1:2 w histeps ti "$_")} @files;

  foreach my $file ( @files ) {
    open SIGNAL, "<$file.warped" or die "can't open $file.warped: $!";
    while ( <SIGNAL> ) {
      chomp;
      s/^\s+//;
      my ( $x, $target, $ladder, $sample, $ladder_w, $ladder_wi, $sample_wi, $df, $dfi ) = split /\s+/;
      if ( $signal eq 'warped ladder' ) {
	push @input, "$x\t$ladder_wi\n";
      }
      elsif ( $signal eq 'warped sample' ) {
	push @input, "$x\t$sample_wi\n";
      }
      else {
	# plot raw sample;
	push @input, "$x\t$sample\n";
      }
    }
    push @input, "e\n";
  }

  open DUMP, ">/tmp/gnuplot.dump";
  print DUMP join("\n", @input);
  close DUMP;

  run3 ['/usr/bin/gnuplot'], \@input, \$read_stdout, \$read_stderr
    or die "couldnt't run3: $!\n";

  if ( $read_stderr ) {
    print STDERR "gnuplot returned this error: $read_stderr";
    die "gnuplot returned this error: $read_stderr";
  }

  return $read_stdout;
}

1;
